﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;

namespace AliCMS.TemplateEngine
{
    internal class IfStatment : Tag
    {
        internal IfStatment(Engine engine, int index, int length, int contentIndex, int contentLength, Tag parent)
            : base(engine, index, length, contentIndex, contentLength, parent)
        {
            _subStatement = new List<SubConditionalStatment>();
        }

        private struct SubConditionalStatment
        {
            internal SubConditionalStatment(int index, int length)
            {
                _index = index;
                _length = length;
            }

            #region Properties
            internal int Index
            {
                get { return _index; }
            }
            internal int Length
            {
                get { return _length; }
            }
            #endregion

            #region Fields
            private int _index;
            private int _length;
            #endregion
        }

        internal override void Init()
        {
            int start = ContentIndex;
            int length = ContentLength;
            Regex re = new Regex(@"(<%ElseIf\b.*?%>)|(<%Else%>)", RegexOptions.Compiled);
            while (true)
            {
                Match match = re.Match(Engine.Text, start, length);
                if (!match.Success)
                    break;

                bool isMine = true;
                for (int i = 0; i < ChildTags.Count; i++)
                {
                    if (match.Index > ChildTags[i].Index && match.Index < ChildTags[i].Index + ChildTags[i].Length)
                    {
                        isMine = false;
                        break;
                    }
                }

                if (isMine)
                {
                    SubConditionalStatment subStatement = new SubConditionalStatment(match.Index, match.Length);
                    _subStatement.Add(subStatement);

                    if (match.Length == 8)
                        break;
                }

                start = match.Index + match.Length;
                length = ContentIndex + ContentLength - start;
            }
        }
        internal override void Parse()
        {
            ParseToCode();
            ParseToXml();
        }

        private void ParseToCode()
        {
            StringBuilder result = new StringBuilder();

            int start = 0;
            int length = 0;

            result.Append("string " + UniqueName + " = String.Empty;\r\n");
            for (int i = -1; i < _subStatement.Count; i++)
            {
                if (i == -1)
                    start = ContentIndex;
                else
                    start = _subStatement[i].Index + _subStatement[i].Length;

                if (i == _subStatement.Count - 1)
                    length = ContentIndex + ContentLength - start;
                else
                    length = _subStatement[i + 1].Index - start;

                if (i == -1)
                {
                    result.Append("if (" + Engine.ParseExpression(this, Engine.Text.Substring(Index + 4, ContentIndex - Index - 6)) + ")\r\n{");
                    result.Append(UniqueName + " = _xmlTemplate.SelectSingleNode(\"/\" + \"/" + UniqueName + "/If\").InnerText;");
                }
                else if (_subStatement[i].Length == 8)
                {
                    result.Append("else\r\n{");
                    result.Append(UniqueName + " = _xmlTemplate.SelectSingleNode(\"/\" + \"/" + UniqueName + "/Else\").InnerText;");
                }
                else
                {
                    result.Append("else if (" + Engine.ParseExpression(this, Engine.Text.Substring(_subStatement[i].Index + 8, _subStatement[i].Length - 10)) + ")\r\n{");
                    result.Append(UniqueName + " = _xmlTemplate.SelectSingleNode(\"/\" + \"/" + UniqueName + "/ElseIf" + i + "\").InnerText;");
                }

                for (int j = 0; j < ChildTags.Count; j++)
                {
                    Tag tag = ChildTags[j];

                    if (tag.Index >= start && (tag.Index + tag.Length) <= (start + length))
                    {
                        if (tag is Code)
                        {
                            result.Append(tag.ResultCode);
                        }
                        else if (tag is OutputStatment && !(tag as OutputStatment).IsAliasStatment)
                        {
                            result.Append("object " + tag.UniqueName + " = " + tag.ResultCode + ";\r\n");
                            result.Append(UniqueName + " = " + UniqueName + ".Replace(\"{#" + tag.UniqueName + "#}\"," + tag.UniqueName + " == null ? \"\" : " + tag.UniqueName + ".ToString());\r\n");
                        }
                        else if (tag is IfStatment)
                        {
                            result.Append(tag.ResultCode);
                            result.Append(UniqueName + " = " + UniqueName + ".Replace(\"{#" + tag.UniqueName + "#}\"," + tag.UniqueName + ");\r\n");
                        }
                        else if (tag.ResultCode != null && Regex.IsMatch(tag.ResultCode, "protected string " + tag.UniqueName + @"\s+{\s+get\s+"))
                        {
                            result.Append(UniqueName + " = " + UniqueName + ".Replace(\"{#" + tag.UniqueName + "#}\"," + tag.UniqueName + ");\r\n");
                        }
                    }
                }

                result.Append("}\r\n");
            }

            ResultCode = result.ToString();
        }
        private void ParseToXml()
        {
            StringBuilder result = new StringBuilder();

            int start = 0;
            int length = 0;
            StringBuilder value = new StringBuilder();

            for (int i = -1; i < _subStatement.Count; i++)
            {
                if (i == -1)
                    start = ContentIndex;
                else
                    start = _subStatement[i].Index + _subStatement[i].Length;

                if (i == _subStatement.Count - 1)
                    length = ContentIndex + ContentLength - start;
                else
                    length = _subStatement[i + 1].Index - start;

                if (i == -1)
                    result.Append("<If><![CDATA[<%Value%>]]></If>");
                else if (_subStatement[i].Length == 8)
                    result.Append("<Else><![CDATA[<%Value%>]]></Else>");
                else
                    result.Append("<ElseIf" + i + "><![CDATA[<%Value%>]]></ElseIf" + i + ">");

                value.Remove(0, value.Length);
                value.Append(Engine.Text.Substring(start, length));

                for (int j = ChildTags.Count - 1; j >= 0; j--)
                {
                    Tag tag = ChildTags[j];

                    if (tag.Index >= start && (tag.Index + tag.Length) <= (start + length))
                    {
                        value.Remove(tag.Index - start, tag.Length);
                        if (tag is OutputStatment)
                        {
                            if ((tag as OutputStatment).IsAliasStatment)
                                value.Insert(tag.Index - start, "{#" + (tag as OutputStatment).AliasXml + "#}");
                            else
                                value.Insert(tag.Index - start, "{#" + tag.UniqueName + "#}");
                        }
                        if (tag is IfStatment || (tag.ResultCode != null && Regex.IsMatch(tag.ResultCode, "protected string " + tag.UniqueName + @"\s+{\s+get\s+")))
                        {
                            value.Insert(tag.Index - start, "{#" + tag.UniqueName + "#}");
                        }
                    }
                }

                result.Replace("<%Value%>", value.ToString());
            }

            ResultXml = result.ToString();
        }

        #region Fields
        List<SubConditionalStatment> _subStatement;
        #endregion
    }
}
